/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.core.session.json;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.inspur.edp.bef.core.session.BefBizContext;
import com.inspur.edp.cef.designtime.api.json.SerializerUtils;
import com.inspur.edp.cef.spi.jsonser.base.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Map;

public class BefBizContextJsonSerializer extends JsonSerializer<BefBizContext> {
    static ObjectMapper mapper = new ObjectMapper();
    static {
        mapper.registerModule(new JavaTimeModule());
    }
    @Override
    public void serialize(BefBizContext befBizContext, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        SerializerUtils.writeStartObject(jsonGenerator);
        SerializerUtils.writePropertyValue(jsonGenerator,BefBizContextConst.ID, befBizContext.getId());
        SerializerUtils.writePropertyValue(jsonGenerator, BefBizContextConst.CreationDate, befBizContext.getCreationDate());
        if(befBizContext.getItems() != null && befBizContext.getItems().size() > 0){
            SerializerUtils.writePropertyValue(jsonGenerator,BefBizContextConst.Items, writeObject(befBizContext.getItems()));
        }
        if(!StringUtils.isEmpty(befBizContext.getParentId())){
            SerializerUtils.writePropertyValue(jsonGenerator,BefBizContextConst.ParentId, befBizContext.getParentId());
        }
        if(!StringUtils.isEmpty(befBizContext.getSessionId())){
            SerializerUtils.writePropertyValue(jsonGenerator,BefBizContextConst.SessionID, befBizContext.getSessionId());
        }
        SerializerUtils.writeEndObject(jsonGenerator);
    }

    private String writeObject(Map<String, Object> map) {
        String splitOperator1 = "!@";
        String splitOperator2 = "!:";
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, Object> item : map.entrySet()) {
            String key = item.getKey();
            Object value = item.getValue();
            DataTypeEnum dataType = getDataType(value);
            if (dataType == DataTypeEnum.ObjType) {
                try {
                    String str = enCode(value);
                    sb.append(key + splitOperator1 + dataType.getValue() + str + splitOperator2);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            else if(dataType == DataTypeEnum.None){
                sb.append(key + splitOperator1 + dataType.getValue() + "z" + splitOperator2);
            }
            else {
                sb.append(key + splitOperator1 + dataType.getValue() + value + splitOperator2);
            }
        }
        return sb.toString();
    }

    /**
     * Base64编码
     * @param obj
     * @return
     */
    private String enCode(Object obj){
        ByteArrayOutputStream memoryOutStream = new ByteArrayOutputStream();
        try {
            ObjectOutputStream ois = new ObjectOutputStream(memoryOutStream);
            ois.writeObject(obj);
            ois.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        byte[] buffer = memoryOutStream.toByteArray();
        String encode = Base64Utils.enCode(buffer);
        return encode;
    }


    private DataTypeEnum getDataType(Object value){
        DataTypeEnum type = DataTypeEnum.None;
        if(value == null)
            return type;
        switch (value.getClass().getTypeName()){
            case "java.lang.Boolean":
                type = DataTypeEnum.BoolType;
                break;
            case "java.lang.Integer":
                type = DataTypeEnum.IntegerType;
                break;
            case "java.lang.Long":
                type = DataTypeEnum.LongType;
                break;
            case "java.lang.Float":
                type = DataTypeEnum.FloatType;
                break;
            case "java.lang.Double":
                type = DataTypeEnum.DoubleType;
                break;
            case "java.lang.String":
                type = DataTypeEnum.StringType;
                break;
            case "java.lang.Character":
                type = DataTypeEnum.CharType;
                break;
            default:
                type = DataTypeEnum.ObjType;
                break;
        }
        return type;
    }
}
